import Router from '@koa/router';
import User from '../models/user';
import userActivationRedis from '../utils/redis/user';
import communityUtil from '../utils/communityUtil';
import sendMail from '../utils/sendMail';

const router = new Router();

/**
 * @route GET /getAllUsers
 * @desc 获取所有用户
 * @access public
 */
router.get('/getAllUsers', async ctx => {
    const results = await User.findAll({ order: [['id', 'DESC']] });
    ctx.sendSD(results);
});

/**
 * @route GET /getUserById
 * @desc 通过 id 获取所有用户
 * @access public
 */
router.get('/getUserById', async ctx => {
    const { id } = ctx.request.query;
    if (communityUtil.isEmpty(id)) {
        ctx.sendFM('缺少参数');
        return;
    }
    // const result = await User.findByPk(id);
    const result = await User.findOne({ where: { id } });
    ctx.sendSD(result);
});

/**
 * @route POST /register
 * @desc 注册新用户
 * @access public
 */
router.post('/register', async ctx => {
    const { email, password }: { email: string; password: string } = ctx.request.body;
    // 对邮箱密码进行验证，先这样写着吧，有时间再研究一下 validate
    if (communityUtil.isEmpty(email) || communityUtil.isEmpty(password)) {
        ctx.sendFM('缺少参数');
        return;
    }
    if (!communityUtil.validateRegister({ email, password })) {
        ctx.sendFM('邮箱或密码格式有误！');
        return;
    }
    // 检查 redis 是否存在激活码
    const getResult = await userActivationRedis.getActivationInfo(email);
    if (getResult != null) {
        // 已存在，请激活账号
        ctx.sendFM('邮件已发送，请勿重复注册');
        return;
    }
    // 查询数据库，检查该账户是否已注册过
    const findResult = await User.findOne({
        where: { email },
    });
    if (findResult != null) {
        // 已注册
        ctx.sendFM('账号已注册');
        return;
    }
    // 生成激活码
    const activationCode = communityUtil.generateActivationCode();
    // 写入 redis
    const saveResult = await userActivationRedis.setActivationInfo({
        email,
        password,
        activationCode,
    });
    if (!saveResult) {
        // 写入失败
        ctx.sendFM('error');
        return;
    }
    // 发送邮件
    try {
        await sendMail({ email, activationCode });
        ctx.sendSDM({ email }, '邮件发送成功');
    } catch (err) {
        console.error(`邮件发送失败： ${err}`);
        ctx.sendFM('邮件发送失败');
    }
});

/**
 * @route GET /activate
 * @desc 用户激活
 * @access public
 */
router.get('/activate', async ctx => {
    const { email, activationCode } = ctx.request.query;
    // 验证 email 和 activationCode
    if (communityUtil.isEmpty(email) || communityUtil.isEmpty(activationCode)) {
        ctx.sendFM('缺少参数');
        return;
    }
    if (!communityUtil.validateEmail(email as string)) {
        ctx.sendFM('邮件格式有误');
        return;
    }
    // 获取 redis 中的用户信息
    const getResult = await userActivationRedis.getActivationInfo(email as string);
    if (getResult == null) {
        // 过期/已注册
        // 检查是否已经激活成功
        const findResult = await User.findOne({
            where: { email },
        });
        if (findResult) {
            // 已注册激活
            ctx.sendFM('无效操作，该账号已激活！');
            return;
        }
        // 说明激活码过期了
        ctx.sendFM('无效操作，激活码已过期！');
        return;
    }
    // 比较收到的激活码是否无误 compareActivationCode
    const compareResult = communityUtil.compareActivationCode(
        getResult.activationCode,
        activationCode as string,
    );
    if (!compareResult) {
        ctx.sendFM('无效操作，激活码有误');
        return;
    }
    // md5 加密密码
    const password = communityUtil.md5(getResult.password);
    // 写入数据库
    const result = await User.create({
        id: communityUtil.generateuuid(),
        email,
        password,
    });
    // 删除 redis 中的激活码
    await userActivationRedis.delActivationInfo(email as string);
    if (result) {
        // 写入成功
        ctx.sendSDM({ email }, '账号激活成功！');
        return;
    }
    ctx.sendFM('激活失败');
});

/**
 * @route POST /login
 * @desc 用户登陆
 * @access public
 */
router.post('/login', async ctx => {
    const { email, password }: { email: string; password: string } = ctx.request.body;
    // 验证邮箱和密码
    if (communityUtil.isEmpty(email) || communityUtil.isEmpty(password)) {
        ctx.sendFM('缺少参数');
        return;
    }
    if (!communityUtil.validateLogin({ email, password })) {
        ctx.sendFM('邮箱或密码格式错误！');
        return;
    }
    // 查询数据库
    const findResult = await User.findOne({
        where: { email },
    });
    if (!findResult) {
        ctx.sendFM('账号不存在！');
        return;
    }
    // 检查密码是否正确
    const compareResult = communityUtil.compareMd5(password, findResult.password);
    if (!compareResult) {
        ctx.sendFM('密码错误');
        return;
    }
    // 生成 token
    const token = communityUtil.generateToken({
        id: findResult.id,
        email: findResult.email,
    });
    ctx.sendSD({
        account: findResult.account,
        email,
        token,
    });
});

/**
 * @route GET /getUser
 * @desc 根据 token 获取用户信息
 * @access public
 */
interface PayloadType {
    id: string;
    email: string;
}
router.get('/getUser', async ctx => {
    const data = ctx.state.user as PayloadType;
    if (communityUtil.isEmpty(data.id) || communityUtil.isEmpty(data.email)) {
        ctx.sendFM('缺少参数');
        return;
    }
    try {
        const findResult = await User.findByPk(data.id);
        if (findResult == null) {
            ctx.sendFM('无效 token');
            return;
        }
        ctx.sendSD({
            id: findResult.id,
            email: findResult.email,
        });
    } catch (err) {
        console.log(err);
        ctx.sendFM('token 失效');
    }
});

export default router;
